module ft232h_to_sdpb (
    // FT232H 接口信号
    input wire ft_clk,         // FT232H 时钟 (通常 60MHz)
    inout wire [7:0] ft_data,  // 双向数据总线
    input wire ft_rxf_n,       // RX FIFO 空标志（低电平有效）
    input wire ft_txe_n,       // TX FIFO 满标志（低电平有效）
    output wire ft_rd_n,       // 读使能（低电平有效）
    output wire ft_wr_n,       // 写使能（低电平有效）
    output wire ft_oe_n,       // 输出使能（低电平有效）
    
    // 系统信号
    input wire sys_clk,        // 系统时钟
    input wire reset_n         // 系统复位（低电平有效）
);

    // SDPB 配置参数
    parameter ADDR_WIDTH = 12;  // 地址宽度，决定 BRAM 大小 (2^12 = 4096)
    parameter DATA_WIDTH = 8;   // 数据宽度，与 FT232H 匹配
    
    // 状态机状态定义
    typedef enum logic [2:0] {
        IDLE,
        READ_FT_DATA,
        WRITE_BRAM,
        DONE
    } state_t;
    
    state_t current_state, next_state;
    
    // SDPB 控制信号
    reg [ADDR_WIDTH-1:0] bram_addr;
    reg [DATA_WIDTH-1:0] bram_data;
    reg bram_wr_en;
    wire [DATA_WIDTH-1:0] bram_q;  // BRAM 输出数据（本例未使用）
    
    // FT232H 控制信号
    assign ft_oe_n = 1'b0;        // 始终使能输出
    assign ft_rd_n = (current_state == READ_FT_DATA) ? 1'b0 : 1'b1;
    assign ft_wr_n = 1'b1;        // 本例中不写回 FT232H
    
    // 双向数据总线处理
    assign ft_data = (ft_rd_n == 1'b0) ? 8'hZZ : 8'hZZ; // 高阻态，仅读取
    wire [DATA_WIDTH-1:0] ft_data_in = ft_data;
    
    // Gowin SDPB 实例化
    SDPB #(
        .ADDR_WIDTH(ADDR_WIDTH),
        .DATA_WIDTH(DATA_WIDTH),
        .INIT_FILE(""),          // 可选初始化文件
        .READ_MODE(0)            // 0: bypass模式; 1: pipeline模式
    ) u_sdpb (
        .clka(sys_clk),          // 写时钟
        .cea(1'b1),              // 时钟使能
        .reseta(~reset_n),      // 复位（高有效）
        .wrea(bram_wr_en),      // 写使能
        .ada(bram_addr),         // 写地址
        .dia(bram_data),        // 写数据
        .clkb(sys_clk),          // 读时钟（本例中未使用读端口）
        .ceb(1'b0),              // 读时钟使能（禁用）
        .resetb(~reset_n),       // 读复位
        .ore(1'b0),              // 输出寄存器使能
        .adb({ADDR_WIDTH{1'b0}}),// 读地址（未使用）
        .dob(bram_q)             // 读数据（未使用）
    );
    
    // 主状态机
    always_ff @(posedge sys_clk or negedge reset_n) begin
        if (!reset_n) begin
            current_state <= IDLE;
            bram_addr <= 0;
            bram_wr_en <= 0;
        end else begin
            current_state <= next_state;
            
            // 在 WRITE_BRAM 状态后自动递增地址
            if (current_state == WRITE_BRAM) begin
                bram_addr <= bram_addr + 1;
            end
        end
    end
    
    // 状态转移逻辑
    always_comb begin
        next_state = current_state;
        bram_wr_en = 1'b0;
        bram_data = 0;
        
        case (current_state)
            IDLE: begin
                if (!ft_rxf_n) begin  // FIFO 中有数据
                    next_state = READ_FT_DATA;
                end
            end
            
            READ_FT_DATA: begin
                // 等待一个周期确保数据稳定
                next_state = WRITE_BRAM;
                bram_data = ft_data_in;  // 锁存数据
            end
            
            WRITE_BRAM: begin
                bram_wr_en = 1'b1;      // 使能 BRAM 写入
                
                if (bram_addr == {ADDR_WIDTH{1'b1}}) begin
                    next_state = DONE;  // BRAM 写满
                end else if (ft_rxf_n) begin
                    next_state = IDLE;   // FIFO 为空
                end else begin
                    next_state = READ_FT_DATA;
                end
            end
            
            DONE: begin
                // 可以添加完成后的处理逻辑
                next_state = DONE;
            end
        endcase
    end
    
    // 跨时钟域处理建议（可选）
    // 如果 ft_clk 和 sys_clk 不同步，需要添加 CDC 逻辑
    // 这里简化处理，假设两者同步或频率关系已知
    
endmodule